package cn.infinite.security.provider;

import cn.infinite.security.core.SmsAuthenticateAble;
import cn.infinite.security.error.MobileNotFoundException;
import cn.infinite.security.token.SmsAuthenticationToken;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.Assert;

/**
 * @author zhangqi
 */
@Slf4j
@AllArgsConstructor
public class SmsAuthenticationProvider implements AuthenticationProvider {

    private SmsAuthenticateAble smsAuthenticateAble;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        Assert.isInstanceOf(SmsAuthenticationToken.class, authentication, "unsupported authentication type");
        Assert.isTrue(!authentication.isAuthenticated(), "already authenticated");
        SmsAuthenticationToken smsAuthenticationToken = (SmsAuthenticationToken) authentication;
        UserDetails userInfo = null;

        //验证短信验证码
        try {
            userInfo = this.smsAuthenticateAble.smsAuthenticate((String) authentication.getPrincipal(), (
                    (SmsAuthenticationToken) authentication).getCheckCode());
        } catch (MobileNotFoundException e) {
            log.error("用户未注册=>{}", e.getMessage());
            throw e;
        } catch (AuthenticationException e) {
            log.error("sms authenticate error=>{}", e.getMessage());
            throw e;
        }
        if (userInfo == null) {
            throw new InternalAuthenticationServiceException("短信验证码验证失败");
        }
        log.info("验证短信验证码成功，认证成功=>{}", userInfo);

        SmsAuthenticationToken successSmsAuthenticationToken = new SmsAuthenticationToken(userInfo,
                "success", userInfo.getAuthorities());

        //复制详细信息
        successSmsAuthenticationToken.setDetails(smsAuthenticationToken.getDetails());
        return successSmsAuthenticationToken;
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return SmsAuthenticationToken.class.isAssignableFrom(authentication);
    }

}
